﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Runtime.InteropServices;
using System.Collections;

using SuperMapLib;

namespace JR_RouteAlarm.BufferMaking
{
    class Common
    {
        /*定数*/
        public const string FLD_FEATURE_CD = Utility.FEATURE;
        public const string FLD_DAIBUN_CD = Utility.DAIBUN;
        public const string FLD_TSUUSHO_CD = Utility.TSUUSHO;
        public const string FLD_LABEL_TEXT = Utility.LABEL_TEXT;

        /*変数*/
        protected AxSuperMapLib.AxSuperWorkspace superWksp = null;
        public static soDataSource objSource = null;
        protected soDatasets objDSs = null;
        protected Hashtable routeLnWithBfr = null;
        protected Hashtable pointPosWithKrt = new Hashtable();
        protected RouteArea routeInfo = null;
        protected string strDatasourceAlias = String.Empty;
        protected string strRouteDatasetName = String.Empty;
        protected string feature = String.Empty;
        protected string daibun = String.Empty;
        protected string tsuusho = String.Empty;

        public soDatasets ObjDSs
        {
            get
            {
                return objDSs;
            }
        }

        protected void MakeBufferForPart(soGeoLine objFullRoute)
        {
            soGeoPoint[] objPointsDividing = null;

            objPointsDividing = new soGeoPoint[Utility.MAX_CROSSING_POINTS];
            MakeDividingPointsOnRoute(objFullRoute, objPointsDividing);

            int lineCount = 0;
            if (objPointsDividing[0] == null)
            {
                soGeoRegion objBuffer = null;

                Console.WriteLine(
                    String.Format("{0}:{1},\t{2}:{3},\t{4}:{5}\t---{6}/{7}---\t{1},{3},{5}",
                        FLD_FEATURE_CD, feature, FLD_DAIBUN_CD, daibun, FLD_TSUUSHO_CD, tsuusho,
                        ++lineCount, routeLnWithBfr.Count + 1));

                //他線区からの鳴動受信なし

                objBuffer = objFullRoute.SpatialOperator.Buffer2(
                    Utility.BUFFER_ALARM_DISTANCE_2, Utility.BUFFER_ALARM_DISTANCE_2, 0);
                routeLnWithBfr[objFullRoute] = objBuffer;

                //Marshal.ReleaseComObject(objBuffer);
                //objBuffer = null;
            }
            else
            {

                if (objFullRoute.SpatialRelation.Contains(objPointsDividing[0] as soGeometry))
                {
                    MakeDividingBuffer(objFullRoute, objPointsDividing, 0, ref lineCount);
                }
                else
                {
                    throw new Exception("Point wrong!");
                }
            }
        }

        protected void MakeDividingBuffer(soGeoLine objLine, soGeoPoint[] objPoints, int idx, ref int lineCount)
        {
            soGeoLine[] objLines = new soGeoLine[2];
            soPoint tmpPoint = null;
            soGeoRegion objBuffer = null;

            tmpPoint = new soPoint();
            objLines[0] = new soGeoLine();
            objLines[1] = new soGeoLine();

            tmpPoint.x = objPoints[idx].x;
            tmpPoint.y = objPoints[idx].y;
            if (objLine.Split(tmpPoint, objLines[0], objLines[1]))
            {
                bool hasRoute = false;
                ArrayList multiRoutes =
                    routeInfo.routeFtrWithInfo[feature + daibun + tsuusho] as ArrayList;

                if (objPoints[idx + 1] == null)
                {
                    Console.WriteLine(
                        String.Format("{0}:{1},\t{2}:{3},\t{4}:{5}\t---{6}/{7}---\t{1},{3},{5}",
                            FLD_FEATURE_CD, feature, FLD_DAIBUN_CD, daibun, FLD_TSUUSHO_CD, tsuusho,
                            ++lineCount, routeLnWithBfr.Count + 1));

                    objBuffer = objLines[0].SpatialOperator.Buffer2(
                        Utility.BUFFER_ALARM_DISTANCE_2, Utility.BUFFER_ALARM_DISTANCE_2, 0);

                    if (multiRoutes != null)
                    {
                        hasRoute = false;
                        foreach (object route in multiRoutes)
                        {
                            soGeoPoint objPointTmp = (route as RouteArea).StartPoint;
                            if (objLines[0].SpatialRelation.Contains(objPointTmp as soGeometry))
                            {
                                routeLnWithBfr[route as RouteArea] = objBuffer;
                                hasRoute = true;
                                break;
                            }
                        }
                    }

                    if (!hasRoute)
                    {
                        routeLnWithBfr[objLines[0]] = objBuffer;
                    }

                    Console.WriteLine(
                        String.Format("{0}:{1},\t{2}:{3},\t{4}:{5}\t---{6}/{7}---\t{1},{3},{5}",
                            FLD_FEATURE_CD, feature, FLD_DAIBUN_CD, daibun, FLD_TSUUSHO_CD, tsuusho,
                            ++lineCount, routeLnWithBfr.Count + 1));

                    objBuffer = objLines[1].SpatialOperator.Buffer2(
                        Utility.BUFFER_ALARM_DISTANCE_2, Utility.BUFFER_ALARM_DISTANCE_2, 0);

                    if (multiRoutes != null)
                    {
                        hasRoute = false;
                        foreach (object route in multiRoutes)
                        {
                            soGeoPoint objPointTmp = (route as RouteArea).StartPoint;
                            if (objLines[1].SpatialRelation.Contains(objPointTmp as soGeometry))
                            {
                                routeLnWithBfr[route as RouteArea] = objBuffer;
                                hasRoute = true;
                                break;
                            }
                        }
                    }

                    if (!hasRoute)
                    {
                        routeLnWithBfr[objLines[1]] = objBuffer;
                    }
                }
                else
                {
                    Boolean pointContain = false;

                    for (int twoIdx = 0; twoIdx < 2; twoIdx++)
                    {
                        pointContain = false;
                        for (int i = idx + 1; objPoints[i] != null; i++)
                        {
                            if (objLines[twoIdx].SpatialRelation.Contains(objPoints[i] as soGeometry))
                            {
                                pointContain = true;
                                MakeDividingBuffer(objLines[twoIdx], objPoints, i, ref lineCount);
                                break;
                            }
                        }
                        if (!pointContain)
                        {
                            Console.WriteLine(
                                String.Format("{0}:{1},\t{2}:{3},\t{4}:{5}\t---{6}/{7}---\t{1},{3},{5}",
                                    FLD_FEATURE_CD, feature, FLD_DAIBUN_CD, daibun, FLD_TSUUSHO_CD, tsuusho,
                                    ++lineCount, routeLnWithBfr.Count + 1));

                            objBuffer = objLines[twoIdx].SpatialOperator.Buffer2(
                                Utility.BUFFER_ALARM_DISTANCE_2, Utility.BUFFER_ALARM_DISTANCE_2, 0);

                            if (multiRoutes != null)
                            {
                                hasRoute = false;
                                foreach (object route in multiRoutes)
                                {
                                    soGeoPoint objPointTmp = (route as RouteArea).StartPoint;
                                    if (objLines[twoIdx].SpatialRelation.Contains(objPointTmp as soGeometry))
                                    {
                                        routeLnWithBfr[route as RouteArea] = objBuffer;
                                        hasRoute = true;
                                        break;
                                    }
                                }
                            }

                            if (!hasRoute)
                            {
                                routeLnWithBfr[objLines[twoIdx]] = objBuffer;
                            }
                        }
                    }
                }
            }

            Marshal.ReleaseComObject(tmpPoint);
            tmpPoint = null;
            //Marshal.ReleaseComObject(objBuffer);
            //objBuffer = null;
            //Marshal.ReleaseComObject(objLines[0]);
            //objLines[0] = null;
            //Marshal.ReleaseComObject(objLines[1]);
            //objLines[1] = null;
        }

        protected void MakeDividingPointsOnRoute(soGeoLine objRoute, soGeoPoint[] objPointsCrossing)
        //protected void MakeDividingPointsOnRoute(soGeoLine objRoute, ArrayList tmpList)
        {
            soDatasets objDSs = null;
            //soDataset objDSPoint = null;
            //soDatasetVector objDatasetV = null;
            //soRecordset objRS = null;
            //soGeoPoint objPointTmp = null;
            //soGeoPoint[] objPointsCrossing = null;
            soGeoRegion[] objBuffers = null;

            objBuffers = new soGeoRegion[Utility.MAX_ROUTES];
            //objPointsCrossing = new soGeoPoint[Utility.MAX_CROSSING_POINTS];
            //objDSs = objSource.Datasets;

            FindCrossingPointsFromBuffers(objRoute, objBuffers, objPointsCrossing);

            #region 広くポイントを取る
            /*
            objDSPoint = objDSs["キロ標_大宮"];
            //objDatasetV = objDSPoint as soDatasetVector;
            soDataset objDSCopy = null;
            soDatasetVector objDatasetVCopy = null;
            soRecordset objRSCopy = null;

            if (!objSource.IsAvailableDatasetName("datasetCopy"))
            {
                objSource.DeleteDataset("datasetCopy");
            }
            objDSCopy = objSource.CopyDataset(
                objDSPoint, "datasetCopy", false, seEncodedType.scEncodedNONE);
            objDatasetVCopy = objDSCopy as soDatasetVector;
            objRSCopy = objDatasetVCopy.Query("-1 < 0", true, null, "");

            if (objRSCopy != null && objRSCopy.RecordCount > 0)
            {
                if (objRSCopy.IsEOF())
                {
                    objRSCopy.MoveFirst();
                }

                //soGeometry objMetry = null;
                for (; !objRSCopy.IsEOF(); objRSCopy.MoveNext())
                { 
                    //objMetry = objRS.GetGeometry();
                    if (!objRoute.SpatialRelation.Contains(objRSCopy.GetGeometry()))
                    {
                        objRSCopy.Delete();
                    }
                }
                if (!objSource.IsAvailableDatasetName("tmpPointsOnLine"))
                {
                    objSource.DeleteDataset("tmpPointsOnLine");
                }
                objDatasetV = objSource.RecordsetToDataset(objRSCopy, "tmpPointsOnLine", false);
                objRSCopy.Close();
                objDatasetVCopy.Close();
                objDatasetVCopy.ClearRecordsets();
                objSource.DeleteDataset("datasetCopy");

                Marshal.ReleaseComObject(objRSCopy);
                objRSCopy = null;
                Marshal.ReleaseComObject(objDatasetVCopy);
                objDatasetVCopy = null;
                Marshal.ReleaseComObject(objDSCopy);
                objDSCopy = null;

                soPoint tmpPoint = null;
                for (int i = 0; i < Utility.MAX_CROSSING_POINTS; i++)
                {
                    if (objPointsCrossing[i] == null)
                    {
                        break;
                    }
                    objRS = objDatasetV.QueryByDistance(
                        objPointsCrossing[i] as soGeometry, Utility.KIROTEI_DISTANCE, "");
                    if (objRS != null && objRS.RecordCount > 0)
                    {
                        objRS.MoveFirst();
                        for (; !objRS.IsEOF(); objRS.MoveNext())
                        {
                            objPointTmp = objRS.GetGeometry() as soGeoPoint;
                            tmpPoint = new soPoint();
                            tmpPoint.x = Math.Ceiling(objPointTmp.x);
                            tmpPoint.y = Math.Ceiling(objPointTmp.y);
                            for (int j = 0; j < objBuffers.Length; j++)
                            {
                                if (objBuffers[j] == null)
                                {
                                    break;
                                }
                                if (!objPointTmp.SpatialRelation.Within(objBuffers[j] as soGeometry))
                                {
#if RELEASE
                                    objPointTmp = objRS.GetGeometry() as soGeoPoint;
#endif
                                    //objPointsDividing[i] = objPointTmp;
                                    if (!tmpList.Contains(tmpPoint))
                                    {
#if DEBUG
                                        Console.WriteLine("x={0}, y={1}, j={2}, i={3}", objPointTmp.x, objPointTmp.y, j, i);
#endif
                                        tmpList.Add(tmpPoint);
                                        //dividingPoints.Add2(objPointTmp.x, objPointTmp.y);
                                    }
                                    continue;
                                }
                            }
                        }
                        objRS.Close();
                    }
                }
                objDatasetV.Close();
                objDatasetV.ClearRecordsets();
                objSource.DeleteDataset("tmpPointsOnLine");

                //Marshal.ReleaseComObject(objMetry);
                //objMetry = null;
            }
             */
            #endregion

            //Marshal.ReleaseComObject(objPointTmp);
            //objPointTmp = null;
            //Marshal.ReleaseComObject(objDatasetV);
            //objDatasetV = null;
            //Marshal.ReleaseComObject(objRS);
            //objRS = null;
            //Marshal.ReleaseComObject(objDSPoint);
            //objDSPoint = null;
        }

        protected void FindCrossingPointsFromBuffers(soGeoLine objRoute, soGeoRegion[] objBuffers, soGeoPoint[] objPointsCrossing)
        {
            soDataset objDSRegion = null;
            soDatasetVector objDatasetV = null;
            soRecordset objRS = null;
            soPoints tmpPoints = null;
            soGeometry objMetry = null;
            int regionIdx = 0;
            int pointIdx = 0;

            for (int i = 1; i <= objDSs.Count; i++)
            {
                if (objDSs[i].GetDatasetInfo().Name.StartsWith(Utility.BUFFER_TITLE_1000, true, null))
                {
                    objDSRegion = objDSs[i];
                    objDatasetV = objDSRegion as soDatasetVector;
                    objRS = objDatasetV.Query("-1 < 0", true, null, "");
                    if (objRS != null && objRS.RecordCount > 0)
                    {
                        objRS.MoveFirst();
                    }
                    objMetry = objRS.GetGeometry();
                    objRS.Close();
                    objDatasetV.Close();
                    objDatasetV.ClearRecordsets();

                    if (objRoute.SpatialRelation.Crosses(objMetry))
                    {
                        tmpPoints = objRoute.GetCrossings(objMetry);
                        objBuffers[regionIdx++] = objMetry as soGeoRegion;

                        int j = 0;
                        for (; j < tmpPoints.Count; j++)
                        {
                            objPointsCrossing[pointIdx + j] = new soGeoPoint();
                            objPointsCrossing[pointIdx + j].x = tmpPoints[j + 1].x;
                            objPointsCrossing[pointIdx + j].y = tmpPoints[j + 1].y;
                        }
                        pointIdx += j;
                    }
                }
            }

            if (tmpPoints != null)
            {
                Marshal.ReleaseComObject(tmpPoints);
                tmpPoints = null;
            }
            Marshal.ReleaseComObject(objDSRegion);
            objDSRegion = null;
            Marshal.ReleaseComObject(objRS);
            objRS = null;
            Marshal.ReleaseComObject(objDatasetV);
            objDatasetV = null;
        }
    }
}
